#' @useDynLib VICmodel
#' @importFrom Rcpp sourceCpp
#' @importFrom stats convolve median
#' @importFrom utils read.table
NULL

.onLoad <- function(libname, pkgname) {
  if(is.null(getOption('VIC_global_params'))) {
    global_params <- list()
  } else {
    global_params <- getOption('VIC_global_params')
  }

  tmp_params <- list(
    'step_per_day' = 24,
    'snow_step_per_day' = 24,
    'runoff_step_per_day' = 24,
    'start_year' = 1949,
    'start_month' = 1,
    'start_day' = 1,
    'start_sec' = 0,
    'end_year' = 1949,
    'end_month' = 1,
    'end_day' = 10,
    'calendar' = 'gregorian',
    'nlayers' = 3,
    'nbands' = 1,
    'nrootzones' = 3,
    'nnodes' = 3,

    'wind_h' = 10,

    'full_energy' = F,
    'close_energy' = F,
    #'quick_solve' = F,
    #'quick_flux' = F,
    'frozen_soil' = F,
    'lakes' = F,
    'july_tavg' = F,
    'compute_treeline' = F,
    'snow_den' = 0,     # 0 = Bras, 1990, 1 = SNTHRM89
    'baseflow' = 0     # 0 = ARNO, 1 = NIJSSEN2001
  )
  for(param in names(tmp_params))
    if(!(param %in% names(global_params)))
      global_params[[param]] <- tmp_params[[param]]

  options(list('VIC_global_params' = global_params))
}

.onUnload <- function(libpath) {
  library.dynam.unload("VICmodel", libpath)
}

#' Get or set global parameters of the VIC model.
#'
#' @param par Name of the VIC global parameter.
#' @param val Value of the parameter to be set. Will return the
#'            current setting value when not provided.
#'
#' @details
#' The global paremteres are as follows:
#'
#'  \describe{
#'   \item{nlayers}{Integer. Number of moisture layers used by the model. Default = 3.}
#'   \item{nnodes}{Integer. Number of thermal solution nodes in the soil column.}
#'   \item{step_per_day}{Integer. Number of simulation time steps per day. Should be > 4 when full_energy=TRUE or frozen_soil=TRUE.}
#'   \item{snow_step_per_day}{Integer. Number of time steps per day used to solve the snow model (if step_per_day > 1, this should = step_per_day)}
#'   \item{runoff_step_per_day}{Integer. Number of time steps per day used to solve the runoff model (should be >= step_per_day)}
#'   \item{start_year}{Integer. Year of model simulation starts.}
#'   \item{start_month}{Integer. Month of model simulation starts}
#'   \item{start_day}{Integer. Day of model simulation starts}
#'   \item{start_sec}{Integer. Second of model simulation starts (e.g., start_sec = 0 means starting from the beginning of a day; start_sec = 3600 for starting from the beginning of the second hour of a day). Default = 0.}
#'   \item{nrecs}{Integer. Number of time steps over which to run model. The number of records must be defined such that the model completes the last day. Either??nrecs or end_year, end_month, and end_day must be specified, but??not both.}
#'   \item{end_year}{Integer. Year of model simulation ends.}
#'   \item{end_month}{Integer. Month of model simulation ends}
#'   \item{end_day}{Integer. Day of model simulation ends}
#'   \item{calendar}{Boolean. Calendar to use. Calendar to use. Must be one of: "standard", "gregorian", "proleptic_gregorian", "noleap", "365_day", "360_day", "julian", "all_leap", "366_day."}
#'   \item{time_units}{Boolean. Units for output time variables. Units for output time variables. Should be one of "days", "hours", "minutes", "seconds". Default = days.}
#'   \item{full_energy}{Boolean. Option for computing land surface temperature (soil or snowpack surface). TRUE??= compute (via iteration) the temperature that balances the surface energy budget. FALSE??= set surface temperature equal to air temperature. Default = False.}
#'   \item{close_energy}{Boolean. Option for controlling links between the energy balances of the surface and the canopy. TRUE??= iterate between the canopy and surface energy balances until they are consistent. FALSE??= compute the surface and canopy energy balances separately, once per time step.?? Default = FALSE.}
#'   \item{frozen_soil}{Boolean. Option for handling the water/ice phase change in frozen soils. TRUE = account for water/ice phase change (including latent heat). FALSE = soil moisture always remains liquid, even when below 0 C; no latent heat effects and ice content is always 0. Default = FALSE. To activate this option, the user must also set the FS_ACTIVE flag to 1 in the soil parameters (parameter \code{soil} of \code{\link{vic}}) for each grid cell where this option is desired. In other words, the user can choose for some grid cells (e.g. cold areas) to compute ice contents and for others (e.g. warm areas) to skip the extra computation.}
#'   \item{quick_flux}{Boolean. Option for computing the soil vertical temperature profile. TRUE = use the approximate method described by Liang et al. (1999) to compute soil temperatures and ground heat flux; this method ignores water/ice phase changes. FALSE = use the finite element method described in Cherkauer and Lettenmaier (1999) to compute soil temperatures and ground heat flux; this method is appropriate for accounting for water/ice phase changes. Default = FALSE (i.e. use Cherkauer and Lettenmaier, 1999) when running FROZEN_SOIL; and TRUE (i.e. use Liang et al. ,1999) in all other cases.}
#'   \item{implicit}{Boolean. If TRUE the model will use an implicit solution for the soil heat flux equation of Cherkauer and Lettenmaier (1999) (quick_flux is FALSE), otherwise uses original explicit solution. When quick_flux is TRUE the implicit solution has no effect. The user can override this option by setting implicit to FALSE in the global parameters. The implicit solution is guaranteed to be stable for all combinations of time step and thermal node spacing; the explicit solution is only stable for some combinations. If the user sets implicit to FALSE, VIC will check the time step, node spacing, and soil thermal properties to confirm stability. If the explicit solution will not be stable, VIC will exit with an error message. Default = TRUE.}
#'   \item{quick_solve}{Boolean. This option is a hybrid of quick_flux. If TRUE, model will use the method described by Liang et al. (1999) to compute ground heat flux during the surface energy balance iterations, and then will use the method described in Cherkauer and Lettenmaier (1999) for the final solution step. Default = FALSE.}
#'   \item{no_flux}{Boolean. If TRUE model will use a no flux bottom boundary with the finite difference soil thermal solution (i.e. quick_flux = FALSE or full_energy = TRUE or frozen_soil = TRUE). Default = FALSE (i.e., use a constant temperature bottom boundary condition).}
#'   \item{exp_trans}{Boolean. If TRUE the model will exponentially distributes the thermal nodes in the Cherkauer and Lettenmaier (1999) finite difference algorithm, otherwise uses linear distribution. (This is only used if frozen_soil = TRUE). Default = TRUE.}
#'   \item{grnd_flux_type}{Integer. Options for handling ground flux: 0 = use (flawed) formulas for ground flux, delta H, and fusion as in VIC 4.0.6 and earlier. 1 = use formulas from VIC 4.1.0. This option exists for backwards compatibility with earlier releases and likely will be removed in later releases. Default = 1.}
#'   \item{Tfallback}{Boolean. Options for handling failures of T iterations to converge. FALSE = if T iteration fails to converge, report an error. TRUE = if T iteration fails to converge, use the previous time step's T value. This option affects the temperatures of canopy air, canopy snow, ground snow pack, ground surface, and soil T nodes. If TFALLBACK is TRUE, VIC will report the total number of instances in which the previous step's T was used, at the end of each grid cell's simulation. In addition, a time series of when these instances occurred (averaged across all veg tile/snow band combinations) can be written to the outputs, using the following output variables: OUT_TFOL_FBFLAG = time series of T fallbacks in canopy snow T solution. OUT_TCAN_FBFLAG = time series of T fallbacks in canopy air T solution. OUT_SNOWT_FBFLAG = time series of T fallbacks in snow pack surface T solution. OUT_SURFT_FBFLAG = time series of T fallbacks in ground surface T solution. OUT_SOILT_FBFLAG = time series of T fallbacks in soil node T solution (one time series per node). Default = TRUE.}
#'   \item{share_layer_moist}{Boolean. If TRUE, then??if??the soil moisture in the layer that contains more than half of the roots is above the critical point, then the plant's roots in the drier layers can access the moisture of the wetter layer so that the plant does not experience moisture limitation. If FALSE or all of the soil layer moistures are below the critical point, transpiration in each layer is limited by the layer's soil moisture. Default: TRUE.}
#'   \item{spatial_frost}{Integer. Option to allow spatial heterogeneity in soil temperature. 0 = Assume soil temperature is horizontally constant (only varies with depth). > 0 = Assume soil temperatures at each given depth are distributed horizontally with a uniform (linear) distribution and the value would be the number of frost sub-areas (each having a distinct temperature). In this case, even when the mean temperature is below freezing, some portion of the soil within the grid cell at that depth could potentially be above freezing. This requires specifying a frost slope value as an extra field in the soil parametes, so that the minimum/maximum temperatures can be computed from the mean value. The maximum and minimum temperatures will be set to mean temperature +/- frost_slope. Default = 0.}
#'   \item{snow_den}{Boolean. Options for computing snow density. 0 = Use algorithm taken from SNTHRM model.1 = Use traditional VIC algorithm taken from Bras (1990). Default = 0.}
#'   \item{blowing}{Boolean. If TRUE, compute evaporative fluxes due to blowing snow. Default = FALSE.}
#'   \item{blowing_var_threshold}{Boolean. If TRUE, a variable shear stress threshold is used to determine the blowing snow flux. If FALSE, then a fixed threshold is used. See Li and Pomeroy (1997) for details. Default: TRUE.}
#'   \item{blowing_calc_prob}{Boolean. If TRUE, the probability of occurrence of blowing snow is calculated as a function of environmental conditions. If FALSE, then the probability is set to 1. See Lu and Pomeroy (1997) for details. Default: TRUE.}
#'   \item{blowing_simple}{Boolean. If TRUE, the sublimation flux of blowing snow is calculated as a function vapor pressure and wind speed. If FALSE, then additional calculations are made to account for a saltation and suspension layer. See Lu and Pomeroy (1997) for details. Default: FALSE.}
#'   \item{blowing_fetch}{Boolean. This option is only used when BLOWING_SIMPLE is set to FALSE. When this option is set to TRUE, the fetch is accounted for in the calculation of the sublimation flux from blowing snow. If FALSE then the fetch is not used. See Lu and Pomeroy (1997) for details. Default: TRUE.}
#'   \item{blowing_spatial_wind}{Boolean. If TRUE, multiple wind speed ranges, calculated according to a probability distribution, are used to determine the sublimation flux from blowing snow. If FALSE, then a single wind speed is used. See Lu and Pomeroy (1997) for details. Default: TRUE.}
#'   \item{compute_treeline}{Integer. Options for handling above-treeline vegetation. 0 = Do not compute treeline or replace vegetation above the treeline. > 0 means compute the treeline elevation based on average July temperatures; for those elevation bands with elevations above the treeline (or the entire grid cell if nbands = 1 when the grid cell elevation is above the tree line), if they contain vegetation tiles having overstory, replace that vegetation with the vegetation having id that same as the value of this parameter in the vegetation library. You must supply VIC with a July average air temperature in the optional July_Tavg field of the soil parameters (parameter \code{soil} of \code{\link{vic}}), and set the july_tavg option to TRUE so that VIC can read the soil parameters correctly. If lakes=TRUE, compute_treeline must be FALSE. Default = FALSE.}
#'   \item{corrprec}{Boolean. If TRUE correct precipitation for gauge undercatch. This option is not supported when using snow/elevation bands. Default = FALSE.}
#'   \item{spatial_snow}{Boolean. Option to allow spatial heterogeneity in snow water equivalent (yielding partial snow coverage) when the snow pack is melting. FALSE = Assume snow water equivalent is constant across grid cell. TRUE = Assume snow water equivalent is distributed horizontally with a uniform (linear) distribution, so that some portion of the grid cell has 0 snow pack. This requires specifying the max_snow_distrib_slope value as an extra field in the soil parameters (parameter \code{soil} of \code{\link{vic}}). max_snow_distrib_slope should be set to twice the desired minimum spatial average snow pack depth [m]. I.e., if we define depth_thresh to be the minimum spatial average snow depth below which coverage < 1.0, then max_snow_distrib_slope = 2*depth_thresh. Partial snow coverage is only computed when the snow pack has started melting and the spatial average snow pack depth <= max_snow_distrib_slope/2. During the accumulation season, coverage is 1.0. Even after the pack has started melting and depth <= max_snow_distrib_slope/2, new snowfall resets coverage to 1.0, and the previous partial coverage is stored. Coverage remains at 1.0 until the new snow has melted away, at which point the previous partial coverage is recovered. Default = FALSE.}
#'   \item{AERO_resist_cansnow}{Integer. Options for aerodynamic resistance in snow-filled canopy. 0??= Multiply by 10 for latent heat, but do NOT multiply by 10 for sensible heat. When no snow in canopy, use surface aero_resist instead of overstory aero_resist. (As in VIC 4.0.6). 1 = Multiply by 10 for both latent and sensible heat. When no snow in canopy, use surface aero_resist instead of overstory aero_resist. 2 = Multiply by 10 for both latent and sensible heat. Always use overstory aero_resist (snow or bare). 3??= Apply stability correction, instead of multiplying by 10, for both latent and sensible heat. Always use overstory aero_resist (snow or bare).?? NOTE: this option exists for backwards compatibility with earlier releases and likely will be removed in later releases.??Default = 2.}
#'   \item{carbon}{Boolean. Options for simulating carbon cycle or not. FALSE??= do not simulate carbon cycle. TRUE??= simulate carbon cycle.??Default = FALSE.}
#'   \item{RC_mode}{Integer. Determines how canopy resistance is computed. 0??= VIC computes canopy resistance by applying resistance factors to the veg class's minimum canopy resistance listed in the veg library. 1??= VIC computes canopy resistance by applying resistance factors to the canopy resistance corresponding to photosynthetic demand (in the absence of moisture limitation).?? Default = 0.}
#'   \item{veglib_photo}{Boolean. Tells VIC about the contents of the veg library. Options for VEGLIB_PHOTO: FALSE??= veg library does not contain photosynthesis parameters. TRUE = veg library contains photosynthesis parameters. Default = FALSE}
#'   \item{continue_error}{Boolean. Options for handling fatal errors. FALSE??= if simulation of a grid cell encounters an error, exit VIC. TRUE??= if simulation of a grid cell encounters an error, move to next grid cell.??Default = TRUE.}
#'   \item{wind_h}{Numeric. Height [m] of wind speed measurement over bare soil and snow cover. Wind measurement height over vegetation is now read from the vegetation library for all types, the value in the global options only controls the wind height over bare soil and over the snow pack when a vegetation canopy is not defined.}
#'   \item{canopy_layers}{Integer. Number of canopy layers in the model. Default: 3.}
#'   \item{baseflow}{Integer. This option describes the form of the baseflow parameters in the soil parameters (parameter \code{soil} of \code{\link{vic}}): 0 = fields 5-8 of the soil parameters are the standard VIC baseflow parameters; 1 = fields 5-8 of the soil parameters are the baseflow parameters from Nijssen et al (2001) Default = 0.}
#'   \item{july_tavg}{Boolean. If TRUE then VIC will expect an additional column (July_Tavg) in the soil parameters (parameter \code{soil} of \code{\link{vic}}) to contain the gridcell's average July temperature. If your soil parameters contains this optional column, you MUST set this parameter to TRUE so that VIC can read the soil parameters correctly. NOTE: Supplying July average temperature is only required if the compute_treeline option is set to TRUE. Default = FALSE.}
#'   \item{organic}{Boolean. TRUE = the soil parameters (parameter \code{soil} of \code{\link{vic}}) contains 3*Nlayer extra columns. For each layer: the organic fraction, and the bulk density and soil particle density of the organic matter in the soil layer. FALSE = the soil parameters do not contain any information about organic soil, and organic fraction should be assumed to be 0. Default = FALSE.}
#'   \item{nrootzones}{Integer. Number of defined root zones defined for root distribution.}
#'   \item{vegpar_albedo}{Boolean. If TRUE the vegetation parameters (parameter \code{veg} of \code{\link{vic}}) contains the columns for each vegetation type that defines monthly albedo values for each vegetation type for each grid cell. Default = FALSE.}
#'   \item{albedo_src}{Integer. This option tells VIC where to look for ALBEDO values: 1 = Use the ALBEDO values listed in the vegetation library. 2 = Use the ALBEDO values listed in the vegetation parameters (parameter \code{veg} of \code{\link{vic}}). Note: for this to work, vegpar_albedo must be TRUE. 3= Use the albedo values in the parameter \code{forcing_veg} of \code{\link{vic}}. For this to work, albedo must be supplied in code{forcing_veg}. Default = 1.}
#'   \item{vegpar_LAI}{Boolean. If TRUE the vegetation parameters (parameter \code{veg} of \code{\link{vic}}) contains an extra line for each vegetation type that defines monthly LAI values for each vegetation type for each gridcell. Default = FALSE.}
#'   \item{LAI_src}{Boolean. This option tells VIC where to look for LAI values: 1 = Use the LAI values listed in the vegetation library. 2 = Use the LAI values listed in the vegetation parameters (parameter \code{veg} of \code{\link{vic}}). Note: for this to work, vegpar_LAI must be TRUE. 3= Use the LAI values in the parameter \code{forcing_veg} of \code{\link{vic}}. For this to work, albedo must be supplied in code{forcing_veg}. Default = 1.}
#'   \item{veglib_fcan}{Boolean. If TRUE the vegetation library contains monthly FCANOPY values for each vegetation type for each grid cell (between the LAI and ALBEDO values). Default = FALSE.}
#'   \item{vegpar_fcan}{Boolean. If TRUE the vegetation parameters (parameter \code{veg} of \code{\link{vic}}) contains an extra line for each vegetation type that defines monthly FCANOPY values for each vegetation type for each grid cell. Default = FALSE.}
#'   \item{fcan_src}{Boolean. This option tells VIC where to look for FCANOPY values: 0 = Set FCANOPY to 1.0 for all veg classes, all times, and all locations. 1 = Use the FCANOPY values listed in the vegetation library. Note: for this to work, veglib_fcan must be TRUE. 2 = Use the FCANOPY values listed in the vegetation parameters (parameter \code{veg} of \code{\link{vic}}). Note: for this to work, vegpar_fcan must be TRUE. 3= Use the FCANOPY values in the parameter \code{forcing_veg} of \code{\link{vic}}. For this to work, FCANOPY must be supplied in code{forcing_veg} Default = 0.}
#'   \item{nbands}{Integer. Maximum number of snow elevation bands to use. Parameter snowband should be provided for the \code{\link{vic}} function when > 1. Default = 1.}
#'   \item{lakes}{Boolean. Options for if simulate lakes lake parameter or not. Default = FALSE.}
#'   \item{lake_profile}{Boolean. Options for describing lake profile: FALSE??= VIC computes a parabolic depth-area profile for the lake basin. TRUE??= VIC reads user-specified depth-area profile from the lake parameters. Default = FALSE.}
#'   \item{resolution}{Numeric. Width of grid cells, in decimal degree latitude or longitude. Default = none, but must be set by the user to match the grid cell size if the lake model is running.}
#' }
#'
#' @references
#'
#' Bras, R. F., 1990: Hydrology, an introduction to hydrologic science, Addison-Wesley.
#' Cherkauer, K. A. and D. P. Lettenmaier, 1999: Hydrologic effects of frozen soils in the upper Mississippi River basin, J. Geophys. Res., 104(D16), 19,599-19,610.
#' Liang, X., E. F. Wood, and D. P. Lettenmaier, 1999: Modeling ground heat flux in land surface parameterization schemes, J. Geophys. Res., 104(D8), 9581-9600.
#' Nijssen, B.N., R. Schnur and D.P. Lettenmaier, 2001: Global retrospective estimation of soil moisture using the Variable Infiltration Capacity land surface model, 1980-1993, J. Clim., 14(8), 1790-1808, doi:10.1175/1520-0442(2001)014<1790:GREOSM>2.0.CO;2.
#'
#' @export
vic_param <- function(par, val = NULL) {
  global_params <- getOption('VIC_global_params')
  if(is.null(val)) return(global_params[[par]])
  global_params[[par]] <- val
  options(list('VIC_global_params' = global_params))
}
